
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;


@SuppressWarnings("serial")
public class MainPanel extends JPanel implements MouseListener {

	ComponentPanel componentpanel[][] ;
	Component component;
	Empty empty;
	Police police[];
	Racer racer[];
	int polNum=0,racNum=0,tarNum=1,hidNum;
	Thread threadPolice[];
	Thread threadRacer[];
	Thread threadHidden[];
	int componentPanelSize;
	public TemporalDifference temporal;
	Lock lock;
	public MainPanel(int componentPanelSize){
		temporal = defaultTD();
		empty = new Empty();
		component = new Empty();
		lock = new ReentrantLock();
		police = new Police[3];
		racer = new Racer[3];
		threadPolice = new Thread[3];
		threadRacer = new Thread[3];
		threadHidden = new Thread[4];
		this.componentPanelSize=componentPanelSize;
		componentpanel= new ComponentPanel[componentPanelSize][componentPanelSize];
		setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
		setLayout(new GridLayout(componentPanelSize,componentPanelSize,0,0));
		addComponentPanel();
		
		
	}
	
	public void addComponentPanel(){
		for(int i=0; i<componentPanelSize; i++)
			for(int j=0; j<componentPanelSize; j++){
		    
				componentpanel[i][j]= new ComponentPanel(componentPanelSize);
				componentpanel[i][j].addMouseListener(this);
				add(componentpanel[i][j]);
			}
	}
	public void moveComponent(){
		for(int i=0; i<3; i++){
			if(threadPolice[i]!=null){
				threadPolice[i].start();
			}
			if(threadRacer[i]!=null)
				threadRacer[i].start();
		}
		for(short i = 0;i<4;i++)
			if(threadHidden[i]!=null)
			threadHidden[i].start();
		
		for(int i=0; i<12; i++)
			for(int j=0; j<12; j++){
				componentpanel[i][j].removeMouseListener(this);
			}
	}
	@SuppressWarnings("deprecation")
	public void stopComponent(){
		for(int i=0; i<3; i++){
			if(threadPolice[i]!=null)
				threadPolice[i].suspend();
			if(threadRacer[i]!=null)
				threadRacer[i].suspend();
		}
		for(short i = 0;i<4;i++)
			if(threadHidden[i]!=null)
				threadHidden[i].suspend();
	}
	
	@SuppressWarnings("deprecation")
	public void resumeComponent() {
		for(int i=0; i<3; i++){
			if(threadPolice[i]!=null)
				threadPolice[i].resume();
			if(threadRacer[i]!=null)
				threadRacer[i].resume();
		}
		for(short i = 0;i<4;i++)
			if(threadHidden[i]!=null)
				threadHidden[i].resume();
	}
	
	public void mouseClicked(MouseEvent arg0) {}

	public void mouseEntered(MouseEvent arg0) {}

	public void mouseExited(MouseEvent arg0) {}

	public void mousePressed(MouseEvent arg0) {
		
		for(int i=0; i<componentPanelSize; i++)
			for(int j=0; j<componentPanelSize; j++){
				if(arg0.getSource()==componentpanel[i][j]){

					if(component instanceof Police && polNum<3){
				    	
				         componentpanel[i][j].putComponent(component.getImage());
				         componentpanel[i][j].removeMouseListener(this);
				    	 police[polNum] = new Police(componentPanelSize,polNum);
				    	 police[polNum].initialState = new State(i,j);
				    	 police[polNum].currentState = new State(i,j);
				    	 componentpanel[i][j].component = police[polNum];
				    	 police[polNum].temporal = temporal;
				    	 threadPolice[polNum] = new Thread(new MovePolice(police[polNum],componentpanel,componentPanelSize,lock));
                         polNum++;
				    
					}
				     
				     if(component instanceof Racer && racNum<3){
				         componentpanel[i][j].putComponent(component.getImage());
				         componentpanel[i][j].removeMouseListener(this);
				    	 racer[racNum] = new Racer(componentPanelSize,racNum);
				    	 racer[racNum].initialState = new State(i,j);
				    	 componentpanel[i][j].component = racer[racNum];
				    	 racer[racNum].currentState = new State(i,j);
				    	 
				    	 racer[racNum].temporal = temporal;
				    	 threadRacer[racNum] = new Thread(new MoveRacer(racer[racNum],componentpanel,componentPanelSize,lock));
				    	 racNum++;

				     }
				     
				     if(component instanceof Obstacle){
				    	
				    	 componentpanel[i][j].component=component;
				         componentpanel[i][j].putComponent(component.getImage());
				         componentpanel[i][j].removeMouseListener(this);
				    
				     }
				     
				     if(component instanceof Target && tarNum==1){
				    	 
				    	 componentpanel[i][j].component=component;
				         componentpanel[i][j].putComponent(component.getImage());
				         component.initialState = new State(i,j);
				         component.currentState = new State(i,j);
				         componentpanel[i][j].removeMouseListener(this);
				         tarNum=0;
				     }
				     
				     if(component== null && hidNum<4){
					    	
				    	 componentpanel[i][j].setBorder(new LineBorder(Color.red,1));
				         componentpanel[i][j].removeMouseListener(this);
				         componentpanel[i][j].isHidden = true;
				         threadHidden[hidNum] = new Thread(new HiddenFlash(componentpanel[i][j]));
				         hidNum++;
				         
				     }
				     
				}
				
			}
	}

	public void mouseReleased(MouseEvent arg0) {}
	
	public Sarsa defaultTD(){
		return new Sarsa(0.5,0.5,0.1,0);
	}
class HiddenFlash implements Runnable{
	
		boolean isHidden = true;
		ComponentPanel c;
		public HiddenFlash(ComponentPanel c){	
			this.c = c;
		}
		
		public void run(){
		
			try {
				
				while(true){
					Thread.sleep(500);
					if(isHidden==true){
						
						c.putComponent(new ImageIcon("picture/free.png").getImage());
						isHidden = false;
					}
					else {
						c.putComponent(c.component.getImage());
						isHidden = true;	
					}
				}
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
}